"""Route planning routes."""
import uuid
from flask import request, current_app
from flask_restx import Namespace, Resource, fields
from flask_jwt_extended import jwt_required, get_jwt_identity
from app.models.location import Location
from app.models.user import User
from app.models.poi import POI
from app.utils.error_handler import ErrorResponse, get_user_friendly_error_message
from app.routes.mock_data import get_mock_pois, MOCK_WEATHER

api = Namespace('route', description='Route planning operations')

# Models
location_model = api.model('Location', {
    'latitude': fields.Float(required=True),
    'longitude': fields.Float(required=True),
    'accuracy': fields.Float(required=True)
})

search_pois_model = api.model('SearchPOIs', {
    'location': fields.Nested(location_model, required=True),
    'radius_meters': fields.Integer(default=3000)
})

generate_route_model = api.model('GenerateRoute', {
    'start_location': fields.Nested(location_model, required=True),
    'target_poi_id': fields.String(required=True)
})

replan_route_model = api.model('ReplanRoute', {
    'current_location': fields.Nested(location_model, required=True),
    'choice': fields.String(required=True, enum=['home', 'next'], description='home or next')
})


@api.route('/search-pois')
class SearchPOIs(Resource):
    """Search nearby POIs endpoint."""
    
    @api.expect(search_pois_model)
    def post(self):
        """Search for nearby POIs.
        
        Validates: Requirements 1.3, 1.4
        """
        data = request.get_json()
        
        # Parse location
        location_data = data.get('location')
        if not location_data:
            api.abort(400, 'location is required')
        
        try:
            location = Location(**location_data)
        except Exception as e:
            api.abort(400, f'Invalid location data: {str(e)}')
        
        radius_meters = data.get('radius_meters', 3000)
        
        # Try to get real POI data, fallback to mock data
        try:
            from app.services.route_planner_service import RoutePlannerService
            
            tencent_map_key = current_app.config.get('TENCENT_MAP_KEY')
            if tencent_map_key:
                route_planner = RoutePlannerService(tencent_map_key)
                pois = route_planner.search_nearby_pois(location, radius_meters)
                pois_list = [poi.to_dict() for poi in pois]
                
                return {
                    'success': True,
                    'pois': pois_list,
                    'count': len(pois_list)
                }, 200
        except Exception as e:
            current_app.logger.warning(f'POI search failed, using mock data: {e}')
        
        # Return mock POI data as fallback
        mock_pois = get_mock_pois(location.latitude, location.longitude)
        return {
            'success': True,
            'pois': mock_pois,
            'count': len(mock_pois),
            'is_mock': True
        }, 200


@api.route('/generate')
class GenerateRoute(Resource):
    """Generate route endpoint."""
    
    @api.expect(generate_route_model)
    def post(self):
        """Generate route to selected POI.
        
        Validates: Requirements 1.3, 1.4
        """
        data = request.get_json()
        
        # Parse start location
        location_data = data.get('start_location')
        if not location_data:
            api.abort(400, 'start_location is required')
        
        try:
            start_location = Location(**location_data)
        except Exception as e:
            api.abort(400, f'Invalid start_location: {str(e)}')
        
        # Get target POI
        target_poi_id = data.get('target_poi_id')
        if not target_poi_id:
            api.abort(400, 'target_poi_id is required')
        
        # Try to find POI in database, or use mock data
        target_poi = POI.query.get(target_poi_id)
        
        # If POI not found in database, create mock route
        if not target_poi:
            # Generate mock route for development
            mock_pois = get_mock_pois(start_location.latitude, start_location.longitude)
            mock_poi = next((p for p in mock_pois if p['id'] == target_poi_id), mock_pois[0] if mock_pois else None)
            
            if mock_poi:
                route_id = str(uuid.uuid4())
                return {
                    'success': True,
                    'route': {
                        'id': route_id,
                        'start_location': {
                            'latitude': start_location.latitude,
                            'longitude': start_location.longitude
                        },
                        'end_location': {
                            'latitude': mock_poi['latitude'],
                            'longitude': mock_poi['longitude']
                        },
                        'waypoints': [
                            {'latitude': start_location.latitude, 'longitude': start_location.longitude},
                            {'latitude': mock_poi['latitude'], 'longitude': mock_poi['longitude']}
                        ],
                        'distance_meters': mock_poi['distance'],
                        'estimated_duration': int(mock_poi['distance'] / 80),  # ~80m/min walking
                        'target_poi_id': target_poi_id
                    },
                    'weather': {
                        'temperature': 22.0,
                        'condition': '晴',
                        'humidity': 65,
                        'wind_speed': 3.5,
                        'aqi': 50
                    },
                    'is_mock': True
                }, 200
            else:
                api.abort(404, 'Target POI not found')
        
        # Try real services
        try:
            from app.services.route_planner_service import RoutePlannerService
            from app.services.weather_service import WeatherService
            
            tencent_map_key = current_app.config.get('TENCENT_MAP_KEY')
            qweather_key = current_app.config.get('QWEATHER_KEY')
            redis_url = current_app.config.get('REDIS_URL')
            cache_duration = current_app.config.get('WEATHER_CACHE_DURATION_SECONDS', 1800)
            
            route_planner = RoutePlannerService(tencent_map_key)
            weather_service = WeatherService(qweather_key, redis_url, cache_duration)
            
            # Get weather data
            weather_data = weather_service.get_current_weather(start_location)
            
            # Generate route
            route = route_planner.generate_route_to_poi(start_location, target_poi, weather_data)
            
            return {
                'success': True,
                'route': {
                    'id': route.id,
                    'start_location': {
                        'latitude': route.start_latitude,
                        'longitude': route.start_longitude
                    },
                    'end_location': {
                        'latitude': route.end_latitude,
                        'longitude': route.end_longitude
                    },
                    'waypoints': route.waypoints,
                    'distance_meters': route.distance_meters,
                    'estimated_duration': route.estimated_duration,
                    'target_poi_id': route.target_poi_id
                },
                'weather': {
                    'temperature': weather_data.temperature,
                    'condition': weather_data.condition,
                    'humidity': weather_data.humidity,
                    'wind_speed': weather_data.wind_speed,
                    'aqi': weather_data.aqi
                }
            }, 200
            
        except Exception as e:
            error_response = ErrorResponse.create(e, include_details=current_app.debug)
            return error_response, 500


@api.route('/replan')
class ReplanRoute(Resource):
    """Replan route endpoint."""
    
    @jwt_required()
    @api.expect(replan_route_model)
    def post(self):
        """Replan route based on user choice.
        
        Validates: Requirements 1.6
        """
        user_id = get_jwt_identity()
        user = User.query.get(user_id)
        
        if not user:
            api.abort(404, 'User not found')
        
        data = request.get_json()
        
        # Parse current location
        location_data = data.get('current_location')
        if not location_data:
            api.abort(400, 'current_location is required')
        
        try:
            current_location = Location(**location_data)
        except Exception as e:
            api.abort(400, f'Invalid current_location: {str(e)}')
        
        # Get choice
        choice = data.get('choice')
        if choice not in ['home', 'next']:
            api.abort(400, 'choice must be "home" or "next"')
        
        # Check if user has home location set
        if choice == 'home':
            if not user.home_latitude or not user.home_longitude:
                api.abort(400, 'User home location is not set')
            
            home_location = Location(
                latitude=user.home_latitude,
                longitude=user.home_longitude,
                accuracy=user.home_accuracy or 10.0
            )
        else:
            home_location = None
        
        # Initialize route planner service
        tencent_map_key = current_app.config.get('TENCENT_MAP_KEY')
        if not tencent_map_key:
            api.abort(500, 'Map service is not configured')
        
        route_planner = RoutePlannerService(tencent_map_key)
        
        try:
            # Replan route
            if choice == 'home':
                new_route = route_planner.replan_route(
                    current_location,
                    'home',
                    home_location,
                    []
                )
            else:
                # Search for available POIs
                available_pois = route_planner.search_nearby_pois(current_location)
                new_route = route_planner.replan_route(
                    current_location,
                    'next',
                    home_location,
                    available_pois
                )
            
            return {
                'success': True,
                'route': {
                    'id': new_route.id,
                    'start_location': {
                        'latitude': new_route.start_latitude,
                        'longitude': new_route.start_longitude
                    },
                    'end_location': {
                        'latitude': new_route.end_latitude,
                        'longitude': new_route.end_longitude
                    },
                    'waypoints': new_route.waypoints,
                    'distance_meters': new_route.distance_meters,
                    'estimated_duration': new_route.estimated_duration,
                    'target_poi_id': new_route.target_poi_id
                }
            }, 200
            
        except Exception as e:
            error_response = ErrorResponse.create(e, include_details=current_app.debug)
            return error_response, 500
